package com.example.identifyvisio.service;

import com.example.identifyvisio.model.R;
import com.example.identifyvisio.model.component.Position;
import com.example.identifyvisio.model.connect.Connect;
import com.example.identifyvisio.model.lane.PositionAndLane;
import com.example.identifyvisio.model.lane.PositioningBasis;
import com.example.identifyvisio.model.node.judge.Judge;
import com.example.identifyvisio.model.lane.Lane;
import com.example.identifyvisio.model.node.serviceNode.ServiceNode;
import com.example.identifyvisio.model.node.startingnode.Node;
import com.example.identifyvisio.model.node.startingnode.failnode.FailNode;
import com.example.identifyvisio.model.node.startingnode.startnode.StartNode;
import com.example.identifyvisio.model.node.startingnode.succeednode.SucceedNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
// ctrl alt o
import java.io.File;
import java.util.*;

import static com.example.identifyvisio.service.ConnectService.getConnect;
import static com.example.identifyvisio.service.JudgeService.getJudge;
import static com.example.identifyvisio.service.LaneService.getLane;
import static com.example.identifyvisio.service.NodeService.*;
import static com.example.identifyvisio.service.ServiceNodeService.getServiceNode;
import static com.example.identifyvisio.utis.VisioFileUtil.getDataMap;
import static com.example.identifyvisio.utis.VisioFileUtil.getTypeMap;

/**
 * 返回json
 */
public class LogicalProcessing {

    public static ArrayList<String> parsePageXml(String pageFilePath, HashMap<String, String> typeMap) throws Exception {

        ArrayList<String> pageList = new ArrayList<>(2);


        //存储误差提示信息
        StringBuilder tooltip = new StringBuilder();
        int index = 1;

        //获取整体的数据，第一个为泳道，第二个是节点数据
        ArrayList<HashMap<Integer, Map<String, String>>> dataMapList = getDataMap(pageFilePath, typeMap);
        File xmlFile = new File(pageFilePath);
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(xmlFile);
        doc.getDocumentElement().normalize();
        NodeList shapeConnect = doc.getElementsByTagName("Connect");

        ArrayList<Object> shapes = new ArrayList<>();
        //泳道数据
        HashMap<Integer, Map<String, String>> laneMap = dataMapList.get(0);
        //节点数据
        HashMap<Integer, Map<String, String>> dataMap = dataMapList.get(1);
        //存储定位节点坐标的依据
        PositioningBasis basis = new PositioningBasis();
        HashMap<String, List<Position>> positionHashMap = new HashMap<>();
        basis.setPositionHashMap(positionHashMap);

        for (Integer shapeID : laneMap.keySet()) {
            Map<String, String> shapeMap = laneMap.get(shapeID);
            String type = shapeMap.get("type");

            if ("垂直泳道".equals(type)) {
                R<PositionAndLane> verticalSwimmingLane = getLane(laneMap, dataMap, shapeID, shapeMap, false, basis);
                //垂直泳道
                PositionAndLane positionAndLane = verticalSwimmingLane.getData();
                shapes.add(positionAndLane.getLane());
            } else {
                R<PositionAndLane> horizontalLane = getLane(laneMap, dataMap, shapeID, shapeMap, true, basis);
                //水平泳道
                PositionAndLane positionAndLane = horizontalLane.getData();
                shapes.add(positionAndLane.getLane());
                String msg = horizontalLane.getMsg();
                if (msg != null){
                    tooltip.append(index++ +".");
                    tooltip.append(msg + "\n");
                }
            }
        }
        //节点与父泳道坐标定位依据
        HashMap<String, List<Position>> positionMap = basis.getPositionHashMap();

        for (Integer shapeID : dataMap.keySet()) {
            Map<String, String> shapeMap = dataMap.get(shapeID);
            String type = shapeMap.get("type");
            if (type.contains("泳道")) {
                //泳道上面已经单独处理直接跳过
                continue;
            }
            if ("连接线".equals(type)) {
                //连接线
                R<Connect> connectR = getConnect(dataMap, shapeID, shapeMap,shapeConnect, shapes, positionMap);
                Connect connect = connectR.getData();
                String msg = connectR.getMsg();
                if (msg != null){
                    tooltip.append(index++ +".");
                    tooltip.append(msg + "\n");
                }
                shapes.add(connect);
            } else if ("失败".equals(type)) {
                FailNode failNode = getFail(dataMap, shapeID, shapeMap, positionMap);
                shapes.add(failNode);
            } else if ("成功".equals(type)) {
                SucceedNode succeedNode = getSucceed(dataMap, shapeID, shapeMap, positionMap);
                shapes.add(succeedNode);
            } else if ("判断".equals(type)) {
                //判断节点
                Judge judge = getJudge(dataMap, shapeID, shapeMap, positionMap);
                shapes.add(judge);
            } else if ("流程".equals(type)) {
                //服务节点
                ServiceNode serviceNode = getServiceNode(dataMap, shapeID, shapeMap, positionMap).getData();
                shapes.add(serviceNode);
            } else {
                //未识别的节点，一律按开始节点
//                shapeMap.put("text","开始");
                if (!"开始".equals(type)){
                    tooltip.append(index++ +".");
                    tooltip.append(type + ",该节点未被正确识别，默认以开始节点渲染\n");
                }
                StartNode startNode = getStart(dataMap, shapeID, shapeMap, positionMap);
                shapes.add(startNode);
            }
        }
        // 将泳道信息序列化为JSON
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(shapes);
//        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(shapes);
        pageList.add(json);
        pageList.add(String.valueOf(tooltip));

        return pageList;
    }
}
